#pragma once

/**
 * 缓冲区 Buffer
 * 读写缓冲区:
 * prependable --- readable --- writable
 *      |       |     |      |      |
 *      |       |  可读区域   |   可写区域
 *      |   read_index_  write_index_
 * 预置区域：方便地添加协议头（如消息长度），而无需移动现有数据
 */

#include <stdint.h>

#include <iostream>
#include <string>
#include <vector>

static const uint64_t defaultPrependSize = 8;  // 默认prependable空间大小
static const uint64_t defaultBufferSize = 22;  // 默认Buffer大小

namespace devem {
class Buffer {
public:
    Buffer(uint64_t initBufferSize = defaultBufferSize + defaultPrependSize)
        : buffer_(initBufferSize), read_index_(defaultPrependSize), write_index_(defaultPrependSize) {}

    // read:
    uint64_t Readable() { return write_index_ - read_index_; }

    char* ReadIndex() { return buffer_.data() + read_index_; }

    void MoveReadOffset(uint64_t len);

    void Peek(void* buffer, uint64_t len);

    void Read(void* buffer, uint64_t len);

    std::string PeekString(uint64_t len);

    std::string ReadString(uint64_t len);
    // write:
    uint64_t Writeable() { return buffer_.size() - write_index_; }

    char* WriteIndex() { return buffer_.data() + write_index_; }

    void MoveWriteOffset(uint64_t len);

    void EnsureSpace(uint64_t len);

    void Append(const void* buffer, uint32_t len);

    void Write(const void* buffer, uint32_t len);

    void AppendString(const std::string& str);

    void WriteString(const std::string& str);

    // prepend
    uint64_t Prependable() { return read_index_; }

    // for debug:
    void printBuffer() {
        for (auto& c : buffer_) {
            std::cout << c << " ";
        }
        std::cout << std::endl;
    }

    ~Buffer() {
        read_index_ = 0;
        write_index_ = 0;
    }

private:
    std::vector<char> buffer_;
    uint64_t read_index_;
    uint64_t write_index_;
};

}  // namespace devem

// details...